home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / emstools.arc / ROLODEX.H < prev    next >
Text File  |  1990-02-04  |  46KB  |  1,104 lines

  1. /*******************************************************************/
  2. /* Include MicroSoft's graph facilities for the cursor positioning */
  3. /* and text output capability.                                     */
  4. /*******************************************************************/
  5.  
  6. #include <graph.h>
  7.  
  8. #include <stdio.h>
  9. #include <ctype.h>
  10. #include <dos.h>
  11.  
  12. #include "memlib.h"         /* for function prototypes */
  13.  
  14. /* Special keys used in keyboard input */
  15.  
  16. #define LEFT_ARROW  75
  17. #define RIGHT_ARROW 77
  18. #define BACK_SPACE   8
  19. #define FRONT_TAB    9
  20. #define BACK_TAB    15
  21. #define CRETURN     13
  22. #define DEL         83
  23. #define INS         82
  24. #define F9          67
  25. #define F10         68
  26.  
  27. /* Standard definitions */
  28.  
  29. #define PASSED 0
  30.  
  31. #define FALSE  0
  32. #define TRUE   1
  33.  
  34. #define ACCEPT 1
  35. #define EXIT   0
  36.  
  37. /* Definitions for setting cursor position */
  38.  
  39. #define ROW             26
  40. #define COLUMN           0
  41. #define VIDEO_PAGE      0x00
  42. #define SET_CURSOR_FUNC 0x02
  43. #define BIOS_INT        0x10
  44.  
  45. /* Definitions of starting locations for various */
  46. /* info on the rolodex screen                    */
  47.  
  48. #define LOGO_START_ROW     3
  49. #define LOGO_START_COL     8
  50.  
  51. #define INSIDE_START_ROW   2
  52. #define INSIDE_START_COL  20
  53. #define INSIDE_END_ROW    17
  54. #define INSIDE_END_COL    61
  55.  
  56. #define OUTSIDE_START_ROW  1
  57. #define OUTSIDE_START_COL 16
  58. #define OUTSIDE_END_ROW   25
  59. #define OUTSIDE_END_COL   65
  60.  
  61. #define TOTAL_EXP_MEM_ROW 16
  62. #define TOTAL_EXP_MEM_COL  9
  63.  
  64. #define MAX_BLOCK_ROW     17
  65. #define MAX_BLOCK_COL     14
  66.  
  67. #define MENU_ROW1         22
  68. #define MENU_ROW2         23
  69. #define MENU_ROW3         24
  70. #define MENU_COL           2
  71.  
  72. #define BLOCK_SIZE_ROW    17
  73. #define BLOCK_SIZE_COL    16
  74.  
  75.  
  76. /* Define some sizes of the strings used in the rolodex structure */
  77.  
  78. #define FIRST_NAME_SIZE    10  
  79. #define LAST_NAME_SIZE     20  
  80. #define AREA_CODE_SIZE      3  
  81. #define PHONE_PREFIX_SIZE   3  
  82. #define PHONE_POSTFIX_SIZE  4  
  83. #define ADDR_LINE1_SIZE    30  
  84. #define ADDR_LINE2_SIZE    30  
  85. #define CITY_SIZE          20  
  86. #define STATE_SIZE          2  
  87. #define ZIP_PREFIX_SIZE     5  
  88. #define ZIP_POSTFIX_SIZE    4  
  89. #define NOTES_SIZE         30  
  90.  
  91. /* total size of strings */
  92.  
  93. #define TOTAL_SIZE  FIRST_NAME_SIZE   + LAST_NAME_SIZE     + AREA_CODE_SIZE  + \
  94.                     PHONE_PREFIX_SIZE + PHONE_POSTFIX_SIZE + ADDR_LINE1_SIZE + \
  95.                     ADDR_LINE2_SIZE   + CITY_SIZE          + STATE_SIZE      + \
  96.                     ZIP_PREFIX_SIZE   + ZIP_POSTFIX_SIZE   + NOTES_SIZE
  97.  
  98. /* maximum size of strings */
  99.  
  100. #define MAX_DATA_SIZE 30
  101.  
  102. /* Define positions of the strings used in the rolodex structure */
  103.  
  104. #define FIRST_NAME_POSITION     0    
  105. #define LAST_NAME_POSITION      1    
  106. #define AREA_CODE_POSITION      2    
  107. #define PHONE_PREFIX_POSITION   3    
  108. #define PHONE_POSTFIX_POSITION  4     
  109. #define ADDRESS_LINE1_POSITION  5    
  110. #define ADDRESS_LINE2_POSITION  6    
  111. #define CITY_POSITION           7    
  112. #define STATE_POSITION          8    
  113. #define ZIP_PREFIX_POSITION     9    
  114. #define ZIP_POSTFIX_POSITION   10   
  115. #define NOTES_POSITION         11   
  116.  
  117. /* Rolodex structure */
  118.  
  119. typedef struct
  120.    {
  121.  
  122.    /* strings displayed.  Each string is offset in data */
  123.  
  124.    char    data[TOTAL_SIZE];
  125.  
  126.    /* "pointers" to the next and previous nodes in the list */
  127.  
  128.    int     next_node;
  129.    int     prev_node;
  130.  
  131.    } NODE;
  132.  
  133. /* Size and offset table to show where each string starts in data */
  134. /* Offset table gets initialized in initialize_list.              */
  135.  
  136. int size_table[] =
  137.    { FIRST_NAME_SIZE,    LAST_NAME_SIZE,  AREA_CODE_SIZE,   PHONE_PREFIX_SIZE,
  138.      PHONE_POSTFIX_SIZE, ADDR_LINE1_SIZE, ADDR_LINE2_SIZE,  CITY_SIZE,
  139.      STATE_SIZE,         ZIP_PREFIX_SIZE, ZIP_POSTFIX_SIZE, NOTES_SIZE };
  140.  
  141. int offset_table[12];
  142.  
  143. /* "Pointers" to the start of the list and the currently viewed node */
  144.  
  145. int start_of_list;
  146. int current_view_node;
  147.  
  148. /* Structure describing options on a rolodex card */
  149.  
  150. typedef struct
  151.    {
  152.    char *title;         /* Pointer to a title for this option  */
  153.    int  title_length;   /* Length of title string              */
  154.    int  row;            /* The row this option is on           */
  155.    int  column;         /* The column                          */
  156.    int  back_tab;       /* Which option to go to on a back tab */
  157.    int  front_tab;      /* Ditto for forward tab               */
  158.    int  c_return;       /* Ditto for carraige return           */
  159.    int  number_chars;   /* How many characters in this option  */
  160.    } OPTION;
  161.  
  162. /* Option table used to build the rolodex screen */
  163.  
  164. OPTION option_list[] =
  165.    {
  166.                     /* first_name option (0)         */
  167.    "NAME: ",        /* title                         */
  168.    6,               /* title_length                  */
  169.    3,               /* row                           */
  170.    12,              /* column                        */
  171.    11,              /* back_tab (to notes)           */
  172.    1,               /* front_tab (to last_name)      */
  173.    2,               /* c_return (to area code)       */
  174.    10,              /* number_chars                  */
  175.  
  176.                     /* last_name option (1)          */
  177.    "",              /* title                         */
  178.    0,               /* title_length                  */
  179.    3,               /* row                           */
  180.    23,              /* column                        */
  181.    0,               /* back_tab (to first_name)      */
  182.    2,               /* front_tab (to area_code)      */
  183.    2,               /* c_return (to area code)       */
  184.    20,              /* number_chars                  */
  185.  
  186.                     /* area_code option (2)          */
  187.    "TELEPHONE NUMBER: (",         /* title           */
  188.    19,              /* title_length                  */
  189.    5,               /* row                           */
  190.    25,              /* column                        */
  191.    1,               /* back_tab (to last_name)       */
  192.    3,               /* front_tab (to phone_first_3)  */
  193.    5,               /* c_return (to address line 1)  */
  194.    3,               /* number_chars                  */
  195.                                                 
  196.                     /* phone_first_3 option (3)      */
  197.    ") ",            /* title                         */
  198.    2,               /* title_length                  */
  199.    5,               /* row                           */
  200.    30,              /* column                        */
  201.    2,               /* back_tab (to area_code)       */
  202.    4,               /* front_tab (to phone_last_4)   */
  203.    5,               /* c_return (to address line 1)  */
  204.    3,               /* number_chars                  */
  205.                                                 
  206.                     /* phone_last_4 option (4)       */
  207.    "-",             /* title                         */
  208.    1,               /* title_length                  */
  209.    5,               /* row                           */
  210.    34,              /* column                        */
  211.    3,               /* back_tab (to phone_first_3)   */
  212.    5,               /* front_tab (to address_line_1) */
  213.    5,               /* c_return (to address line 1)  */
  214.    4,               /* number_chars                  */
  215.  
  216.                     /* address_line_1 option (5)     */
  217.    "ADDRESS: ",     /* title                         */                  
  218.    9,               /* title_length                  */
  219.    7,               /* row                           */
  220.    15,              /* column                        */
  221.    4,               /* back_tab (to phone_last_4)    */
  222.    6,               /* front_tab (to address_line_2) */
  223.    6,               /* c_return (to address line 2)  */
  224.    30,              /* number_chars                  */
  225.  
  226.                     /* address_line_2 option (6)     */
  227.    "",              /* title                         */
  228.    0,               /* title_length                  */
  229.    9,               /* row                           */
  230.    15,              /* column                        */
  231.    5,               /* back_tab (to address_line_1)  */
  232.    7,               /* front_tab (to city)           */
  233.    7,               /* c_return (to city)            */
  234.    30,              /* number_chars                  */
  235.  
  236.                     /* city option (7)               */
  237.    "CITY: ",        /* title                         */
  238.    6,               /* title_length                  */
  239.    11,              /* row                           */
  240.    12,              /* column                        */
  241.    6,               /* back_tab (to address_line_2)  */
  242.    8,               /* front_tab (to state)          */
  243.    9,               /* c_return (to zip)             */
  244.    20,              /* number_chars                  */
  245.  
  246.                     /* state option (8)              */
  247.    "STATE: ",       /* title                         */
  248.    7,               /* title_length                  */
  249.    11,              /* row                           */
  250.    39,              /* column                        */
  251.    7,               /* back_tab (to city)            */
  252.    9,               /* front_tab (to zip_first_5)    */
  253.    9,               /* c_return (to zip)             */
  254.    2,               /* number_chars                  */
  255.  
  256.                     /* zip_first_5 option (9)        */
  257.    "ZIP: ",         /* title                         */
  258.    5,               /* title_length                  */
  259.    13,              /* row                           */
  260.    35,              /* column                        */
  261.    8,               /* back_tab (to notes)           */
  262.    10,              /* front_tab (to last_name)      */
  263.    11,              /* c_return (to notes)           */
  264.    5,               /* number_chars                  */
  265.  
  266.                     /* zip_last_4 option (10)        */
  267.    "-",             /* title                         */
  268.    1,               /* title_length                  */
  269.    13,              /* row                           */
  270.    41,              /* column                        */
  271.    9,               /* back_tab (to zip_first_5)     */
  272.    11,              /* front_tab (to notes)          */
  273.    11,              /* c_return (to notes)           */
  274.    4,               /* number_chars                  */
  275.  
  276.                     /* notes option (11)             */
  277.    "NOTES: ",       /* title                         */
  278.    7,               /* title_length                  */
  279.    16,              /* row                           */
  280.    13,              /* column                        */
  281.    10,              /* back_tab (to zip_last_4)      */
  282.    0,               /* front_tab (to first_name)     */
  283.    0,               /* c_return (to first_name)      */
  284.    30               /* number_chars                  */
  285.    };
  286.  
  287. const NUMBER_OF_OPTIONS = sizeof(option_list) / sizeof(OPTION);
  288.  
  289.  
  290. void abort(), main();
  291.  
  292. unsigned int initialize_list(), save_list(), display_total_exp_mem();
  293. unsigned int display_max_block(), display_block_size(), show_node();
  294. unsigned int insert_node(), edit_node(), delete_node();
  295.  
  296.  
  297. /* Housekeeping functions for the rolodex */
  298.  
  299. /*$PAGE*/
  300. /**********************************************************************/
  301. /*                                                                    */
  302. /*     Name:  void hide_cursor (void)                                 */
  303. /*                                                                    */
  304. /*     Description:                                                   */
  305. /*        Hide the cursor by making a call to the set cursor function */
  306. /*     within BIOS.  We put the cursor beyond the boundries of the    */
  307. /*     displayable screen.                                            */
  308. /*                                                                    */
  309. /*     Parameters:  None                                              */
  310. /*                                                                    */
  311. /*     Results returned:  None                                        */
  312. /*                                                                    */
  313. /*     Calls: None                                                    */
  314. /*                                                                    */
  315. /*     Called by: main_menu()                                         */
  316. /*                                                                    */
  317. /*     Globals referenced/modified: None                              */
  318. /*                                                                    */
  319. /**********************************************************************/
  320.  
  321. void hide_cursor (void)
  322. {
  323.    union REGS inregs, outregs;
  324.  
  325.    inregs.h.dh = ROW;     
  326.    inregs.h.dl = COLUMN;  
  327.    inregs.h.bh = VIDEO_PAGE;
  328.    inregs.h.ah = SET_CURSOR_FUNC;  /* set cursor position function request */
  329.  
  330.    int86 (BIOS_INT, &inregs, &outregs);
  331. }
  332.  
  333.  
  334. /*$PAGE*/
  335. /**********************************************************************/
  336. /*                                                                    */
  337. /*     Name:  void draw_border (void)                                 */
  338. /*                                                                    */
  339. /*     Description:                                                   */
  340. /*        Draws the border for the rolodex screen display.            */
  341. /*                                                                    */
  342. /*     Parameters:  None                                              */
  343. /*                                                                    */
  344. /*     Results returned:  None                                        */
  345. /*                                                                    */
  346. /*     Calls:  None                                                   */
  347. /*                                                                    */
  348. /*     Called by: main()                                              */
  349. /*                                                                    */
  350. /*     Globals referenced/modified:  None                             */
  351. /*                                                                    */
  352. /**********************************************************************/
  353.  
  354. void draw_border (void)
  355.  
  356.    {
  357.     static char *border[] =
  358.        {
  359.        "   ┌───────────────────────────────────────────┐",
  360.        "   │                                           │",
  361.        "   │                                           │",
  362.        "   │                                           │",
  363.        "   │                                           │",
  364.        "   │                                           │",
  365.        "   │                                           │",
  366.        "   │                                           │",
  367.        "   │                                           │",
  368.        "   │                                           │",
  369.        "   │                                           │",
  370.        "   │                                           │",
  371.        "   │                                           │",
  372.        "   │                                           │",
  373.        " ┌┐│                                           │┌┐",
  374.        " │││                                           │││",
  375.        " │││                                           │││",
  376.        " ││└───────────────────────────────────────────┘││",
  377.        " ││                                             ││",
  378.        " └┘                                             └┘"
  379.        };
  380.  
  381.    /* number of border lines to draw */
  382.  
  383.    static int number_of_border_lines = sizeof (border) / sizeof (border[0]);
  384.    int        i;      /* loop                */
  385.    int        row;    /* row to draw line on */
  386.  
  387.    row = 0;
  388.    for (i = 0; i < number_of_border_lines; i++)
  389.        {
  390.  
  391.        /* increment row (start at row 1), set position, and draw */
  392.  
  393.        row++;
  394.        _settextposition (row, 1);
  395.        _outtext (border[i]);
  396.        }
  397.    }  /** end of draw_border **/
  398.  
  399. /*$PAGE*/
  400. /**********************************************************************/
  401. /*                                                                    */
  402. /*     Name:  void draw_logo (void)                                   */
  403. /*                                                                    */
  404. /*     Description:                                                   */
  405. /*        Draws the Intel logo used when viewing first (dummy) node   */
  406. /*     in the list.                                                   */
  407. /*                                                                    */
  408. /*     Parameters:  None                                              */
  409. /*                                                                    */
  410. /*     Results returned:  None                                        */
  411. /*                                                                    */
  412. /*     Calls:  None                                                   */
  413. /*                                                                    */
  414. /*     Called by: show_node()                                         */
  415. /*                                                                    */
  416. /*     Globals referenced/modified:  None                             */
  417. /*                                                                    */
  418. /**********************************************************************/
  419.  
  420. void draw_logo (void)
  421.  
  422.    {
  423.    static char *logo[] =
  424.        {
  425.        " ██             ██            ██  (R)",
  426.        "                ██            ██     ",
  427.        " ██  ██▄███▄  ▀▀██▀▀          ██     ",
  428.        " ██  ██▀  ▀██   ██            ██     ",
  429.        " ██  ██    ██   ██   ▄████▄   ██     ",
  430.        " ██  ██    ██   ██  ██▀  ▀██  ██     ",
  431.        " ██  ██    ██    ▀██████████████     ",
  432.        "                    ██▄              ",
  433.        "                     ▀████▀          ",
  434.        "                                     ",
  435.        "                                     ",
  436.        "               ROLODEX               "
  437.        };
  438.  
  439.    /* Number of lines to draw in the logo */
  440.  
  441.    static int number_of_logo_lines = sizeof(logo) / sizeof(logo[0]);
  442.  
  443.    int        i;      /* loop                */
  444.    int        row;    /* row to draw line on */
  445.  
  446.    row = LOGO_START_ROW;
  447.    for (i = 0; i < number_of_logo_lines; i++)
  448.        {
  449.  
  450.        /* increment row (start at row 4), set position, and draw */
  451.  
  452.        row++;
  453.        _settextposition (row, LOGO_START_COL);
  454.        _outtext (logo[i]);
  455.        }
  456.    }  /** end draw_logo **/
  457.  
  458. /*$PAGE*/
  459. /**********************************************************************/
  460. /*                                                                    */
  461. /*     Name:  void clear_rolodex (void)                               */
  462. /*                                                                    */
  463. /*     Description:                                                   */
  464. /*        Clears the rolodex screen with out erasing the border.      */
  465. /*                                                                    */
  466. /*     Parameters:  None                                              */
  467. /*                                                                    */
  468. /*     Results returned:  None                                        */
  469. /*                                                                    */
  470. /*     Calls:  None                                                   */
  471. /*                                                                    */
  472. /*     Called by:  show_node()                                        */
  473. /*                 edit_fields()                                      */
  474. /*                                                                    */
  475. /*     Globals referenced/modified:  None                             */
  476. /*                                                                    */
  477. /**********************************************************************/
  478.  
  479. void clear_rolodex (void)
  480.  
  481.    {
  482.  
  483.    _settextwindow (INSIDE_START_ROW, INSIDE_START_COL, INSIDE_END_ROW,
  484.                    INSIDE_END_COL);
  485.    _clearscreen (_GWINDOW);
  486.    _settextwindow (OUTSIDE_START_ROW, OUTSIDE_START_COL, OUTSIDE_END_ROW,
  487.                    OUTSIDE_END_COL);
  488.  
  489.    }  /** end clear_rolodex **/
  490.  
  491. /*$PAGE*/
  492. /**********************************************************************/
  493. /*                                                                    */
  494. /*     Name:  int compare_last_names(ptr1, ptr2)                      */
  495. /*            NODE far *ptr1, *ptr2;                                  */
  496. /*                                                                    */
  497. /*     Description:                                                   */
  498. /*        Compares two names - strcmpi won't work on far data items.  */
  499. /*     (Bug in MS C).                                                 */
  500. /*                                                                    */
  501. /*     Parameters:                                                    */
  502. /*        input  ptr1   pointer to last name 1                        */
  503. /*        input  ptr2   pointer to last name 2                        */
  504. /*                                                                    */
  505. /*     Results returned:                                              */
  506. /*        <0   ptr1 < ptr2                                            */
  507. /*        0    ptr1 = ptr2                                            */
  508. /*        >0   ptr1 > ptr2                                            */
  509. /*                                                                    */
  510. /*     Calls:  None                                                   */
  511. /*                                                                    */
  512. /*     Called by: insert_node()                                       */
  513. /*                                                                    */
  514. /*     Globals referenced/modified:  size_table                       */
  515. /*                                   offset_table                     */
  516. /*                                                                    */
  517. /**********************************************************************/
  518.  
  519. int compare_last_names (ptr1, ptr2)
  520. NODE far *ptr1, *ptr2;
  521.  
  522.     {
  523.     char near_1[LAST_NAME_SIZE + 1];   /* local buffer for last name 1 */
  524.     char near_2[LAST_NAME_SIZE + 1];   /* local buffer for last name 2 */
  525.     int  i;                            /* loop                         */
  526.     int  ret;                          /* return value                 */
  527.  
  528.    /************************************/
  529.    /* copy last name 1 to local buffer */
  530.    /************************************/
  531.  
  532.    for (i = 0; i < size_table[1]; i++)
  533.        near_1[i] = ptr1->data[offset_table[LAST_NAME_POSITION] + i];
  534.    near_1[i] = 0;
  535.  
  536.    /************************************/
  537.    /* copy last name 2 to local buffer */
  538.    /************************************/
  539.  
  540.    for (i = 0; i < size_table[1]; i++)
  541.        near_2[i] = ptr2->data[offset_table[LAST_NAME_POSITION] + i];
  542.    near_1[i] = 0;
  543.  
  544.    /***************************************/
  545.    /* Use string compare on local strings */
  546.    /***************************************/
  547.  
  548.    ret = strcmpi (near_1, near_2);
  549.  
  550.    return(ret);
  551.    } /** end compare_last_names **/
  552.  
  553. /*$PAGE*/
  554. /**********************************************************************/
  555. /*                                                                    */
  556. /*     Name: int edit_fields (title_line, this_node)                  */
  557. /*           char *tile_line;                                         */
  558. /*           int this_node;                                           */
  559. /*                                                                    */
  560. /*     Description:                                                   */
  561. /*        To edit the fields in this node.  We must map in the block  */
  562. /*      associated with this node in order to gain access to it.      */
  563. /*                                                                    */
  564. /*     Parameters:                                                    */
  565. /*        input this_node  "pointer" to the node to edit fields in.   */
  566. /*                                                                    */
  567. /*     Results returned:                                              */
  568. /*        ACCEPT ==> accept was picked                                */
  569. /*        EXIT   ==> exit was picked                                  */
  570. /*                                                                    */
  571. /*     Calls:  set1eptr()                                             */
  572. /*             abort()                                                */
  573. /*             clear_rolodex()                                        */
  574. /*             show_node()                                            */
  575. /*                                                                    */
  576. /*     Called by:  insert_node()                                      */
  577. /*                 edit_node()                                        */
  578. /*                                                                    */
  579. /*     Globals referenced/modified:  option_list                      */
  580. /*                                   size_table                       */
  581. /*                                   offset_table                     */
  582. /*                                                                    */
  583. /**********************************************************************/
  584.  
  585. int edit_fields (title_line, this_node)
  586. char *title_line;
  587. int  this_node;
  588.  
  589.    {
  590.    int          cur_option;     /* which option we're on               */
  591.    int          i;              /* loop                                */
  592.    int          pos;            /* column position for INS, DEL        */
  593.    int          cur_char;       /* Current character within an option  */
  594.    unsigned int status;         /* error tarcking                      */
  595.    unsigned int ret_status;     /* return status (EXIT/ACCEPT)         */
  596.    NODE far     *ptr;           /* ptr to a tempoary node              */
  597.    short        row;            /* row we're on for screen positioning */
  598.    short        col;            /* column we're on                     */
  599.    short        key;            /* key that was pressed                */
  600.    short        ext_scan;       /* TRUE/FALSE ext_scan code            */
  601.    static char  out[] = " ";    /* string for _outtext() call          */
  602.    static char  *menu_line[] =  /* bottom menu lines                   */
  603.        {
  604.        "TITLE LINE TITLE LINE TITLE LINE TITLE LINE TITLE",
  605.        "    Use Tab, Larrow and Rarrow to move cursor.   ",
  606.        "  F9 = accept changes  F10 = exit without change "
  607.        };
  608.  
  609.    /******************************************/
  610.    /* Set first menu line to passed in title */
  611.    /******************************************/
  612.  
  613.    menu_line[0] = title_line;
  614.  
  615.    /**********************************/
  616.    /* Get access to the node to edit */
  617.    /**********************************/
  618.  
  619.    status = set1eptr (this_node, &ptr);
  620.  
  621.    if (status != PASSED)
  622.        abort(status);
  623.  
  624.    else
  625.        {
  626.  
  627.        /****************************/
  628.        /* Clear the rolodex screen */
  629.        /****************************/
  630.  
  631.        clear_rolodex();
  632.  
  633.        /*****************************************/
  634.        /* Set spaces in data to '_' for display */
  635.        /*****************************************/
  636.  
  637.        for (i = 0; i < TOTAL_SIZE; i++)
  638.            if (ptr->data[i] == ' ')
  639.                ptr->data[i] = '_';
  640.  
  641.        /******************/
  642.        /* Show this node */
  643.        /******************/
  644.  
  645.        show_node(this_node);
  646.  
  647.        /**********************/
  648.        /* Put up bottom menu */
  649.        /**********************/
  650.  
  651.        _settextposition(MENU_ROW1, MENU_COL);
  652.        _outtext(menu_line[0]);
  653.        _settextposition(MENU_ROW2, MENU_COL);
  654.        _outtext(menu_line[1]);
  655.        _settextposition(MENU_ROW3, MENU_COL);
  656.        _outtext(menu_line[2]);
  657.  
  658.        /***************************************************************/
  659.        /* Set current option and current character within that option */
  660.        /***************************************************************/
  661.  
  662.        cur_option = 0;
  663.        cur_char = 0;
  664.  
  665.        /*************************************************************/
  666.        /* Get key presses until F9 (accept) or F10 (exit) is picked */
  667.        /*************************************************************/
  668.  
  669.        do
  670.            {
  671.  
  672.            /********************************************************/
  673.            /* set the cursor postion to the row,col in option_list */
  674.            /********************************************************/
  675.  
  676.            row = option_list[cur_option].row;
  677.            col = option_list[cur_option].column + cur_char;
  678.            _settextposition (row, col);
  679.  
  680.            /***************************************************/
  681.            /* Get a key press and test for extended scan code */
  682.            /***************************************************/
  683.  
  684.            key = getch();
  685.            if (key == 0)
  686.                {
  687.                ext_scan = TRUE;
  688.                key = getch();
  689.                }
  690.            else
  691.                ext_scan = FALSE;
  692.  
  693.            /* If normal key then ... */
  694.  
  695.            if (!ext_scan)
  696.                switch (key)
  697.                    {
  698.  
  699.                    /***************************************************/
  700.                    /* Carraige return: Set current option to the      */
  701.                    /* option determined by the c_return field of the  */
  702.                    /* option_list.  Set current character to 0.       */
  703.                    /***************************************************/
  704.  
  705.                    case CRETURN:
  706.                        cur_option = option_list[cur_option].c_return;
  707.                        cur_char = 0;
  708.  
  709.                        break;
  710.  
  711.                    /****************************************************/
  712.                    /* Back space: Erase current character in data. Set */
  713.                    /* cursor one space left (if beyond beginning of    */
  714.                    /* option set to previous option).  Set row,col     */
  715.                    /* and output an '-' to screen.                     */
  716.                    /****************************************************/
  717.  
  718.                    case BACK_SPACE:
  719.                        ptr->data[offset_table[cur_option] + cur_char] = '_';
  720.  
  721.                        cur_char--;
  722.                        if (cur_char < 0)
  723.                            {
  724.                            cur_option = option_list[cur_option].back_tab;
  725.                            cur_char = size_table[cur_option] - 1;
  726.                            }
  727.  
  728.                        row = option_list[cur_option].row;
  729.                        col = option_list[cur_option].column + cur_char;
  730.                        _settextposition (row, col);
  731.                        out[0] = '_';
  732.                        _outtext (out);
  733.  
  734.                        break;
  735.  
  736.                    /***************************************************/
  737.                    /* Front Tab:  Set current option the the next     */
  738.                    /* option in option_list.  Set the current         */
  739.                    /* character to 0 (start at beginning of option).  */
  740.                    /***************************************************/
  741.  
  742.                    case FRONT_TAB:
  743.                        cur_option = option_list[cur_option].front_tab;
  744.                        cur_char = 0;
  745.  
  746.                        break;
  747.  
  748.                    /***************************************************/
  749.                    /* Default:  If the key pressed is a printable key */
  750.                    /* then set current character in data to the key.  */
  751.                    /* Increment current character (if beyond the end  */
  752.                    /* of the option, set to next option).  Output the */
  753.                    /* key pressed.                                    */
  754.                    /***************************************************/
  755.  
  756.                    default:
  757.                        if (isprint(key))
  758.                            {
  759.                            ptr->data[offset_table[cur_option] + cur_char] = key;
  760.  
  761.                            cur_char++;
  762.                            if (cur_char >= size_table[cur_option])
  763.                                {
  764.                                cur_char = 0;
  765.                                cur_option = option_list[cur_option].front_tab;
  766.                                }
  767.  
  768.                            out[0] = key;
  769.                            _outtext (out);
  770.  
  771.                            }
  772.  
  773.                            break;
  774.                    } /** end switch **/
  775.  
  776.            else             /* The key pressed was an ext scan code */
  777.                switch (key)
  778.                    {
  779.  
  780.                    /***************************************************/
  781.                    /* Back tab: Set cuurent option to the previous    */
  782.                    /* option in option_list.  Set currrent character  */
  783.                    /* to 0 (beginning of the option).                 */
  784.                    /***************************************************/
  785.  
  786.                    case BACK_TAB:
  787.                        cur_option = option_list[cur_option].back_tab;
  788.                        cur_char = 0;
  789.  
  790.                        break;
  791.  
  792.                    /***************************************************/
  793.                    /* Left arrow: Set current character back one.  If */
  794.                    /* beyond beginning of option set to last character*/
  795.                    /* of previous option.                             */
  796.                    /***************************************************/
  797.  
  798.                    case LEFT_ARROW:
  799.                        cur_char--;
  800.                        if (cur_char < 0)
  801.                            {
  802.                            cur_option = option_list[cur_option].back_tab;
  803.                            cur_char = size_table[cur_option] - 1;
  804.                            }
  805.  
  806.                        break;
  807.  
  808.                    /***************************************************/
  809.                    /* Right arrow:  Set current character up one.  If */
  810.                    /* beyond end of option set to first character of  */
  811.                    /* next option.                                    */
  812.                    /***************************************************/
  813.  
  814.                    case RIGHT_ARROW:
  815.                        cur_char++;
  816.                        if (cur_char >= size_table[cur_option])
  817.                            {
  818.                            cur_option = option_list[cur_option].front_tab;
  819.                            cur_char = 0;
  820.                            }
  821.  
  822.                        break;
  823.  
  824.                    /***************************************************/
  825.                    /* Delete: From the current character to the end   */
  826.                    /* of the current option,  set each character in   */
  827.                    /* data to the next character and output it to the */
  828.                    /* screen.  This effectively deletes the current   */
  829.                    /* character and pulls the rest of the option one  */
  830.                    /* space forward.                                  */
  831.                    /***************************************************/
  832.  
  833.                    case DEL:
  834.                        for (i = cur_char; i < size_table[cur_option]; i++)
  835.                            {
  836.  
  837.                            pos = offset_table[cur_option] + i;
  838.                            if (i < size_table[cur_option] - 1)
  839.                                ptr->data[pos] = ptr->data[pos + 1];
  840.                            else
  841.                                ptr->data[pos] = '_';
  842.  
  843.                            col = option_list[cur_option].column + i;
  844.                            _settextposition (row, col);
  845.                            out[0] = ptr->data[pos];
  846.                            _outtext (out);
  847.                            }
  848.  
  849.                        break;
  850.  
  851.                    /***************************************************/
  852.                    /* Insert: Insert a space at the current location  */
  853.                    /* and push the rest of the option back one space. */
  854.                    /***************************************************/
  855.  
  856.                    case INS:
  857.                        for (i = size_table[cur_option] - 1; i >= cur_char; i--)
  858.                            {
  859.  
  860.                            pos = offset_table[cur_option] + i;
  861.                            if (i > cur_char)
  862.                                ptr->data[pos] = ptr->data[pos - 1];
  863.                            else
  864.                                ptr->data[pos] = '_';
  865.  
  866.                            col = option_list[cur_option].column + i;
  867.                            _settextposition (row, col);
  868.                            out[0] = ptr->data[pos];
  869.                            _outtext(out);
  870.                            }
  871.  
  872.                        break;
  873.  
  874.                    }  /** end switch **/
  875.  
  876.            }  /** end do **/
  877.        while (!ext_scan || ((key != F9) && (key != F10)));
  878.  
  879.        /***********************************************************/
  880.        /* Set status to either FAILED (exit was picked) or PASSED */
  881.        /* (accept was picked).                                    */
  882.        /***********************************************************/
  883.  
  884.        if (key == F10)
  885.            ret_status = EXIT;
  886.        if (key == F9)
  887.            {
  888.            ret_status = ACCEPT;
  889.  
  890.            /*********************************/
  891.            /* Set all underscores to spaces */
  892.            /*********************************/
  893.  
  894.            for (i = 0; i < TOTAL_SIZE; i++)
  895.                if (ptr->data[i] == '_')
  896.                    ptr->data[i] = ' ';
  897.            }
  898.  
  899.        } /** end if status **/
  900.  
  901.    return (ret_status);
  902.  
  903.    } /** end edit_fields **/
  904.  
  905. /*$PAGE*/
  906. /**********************************************************************/
  907. /*                                                                    */
  908. /*     Name:  void main_menu (void)                                   */
  909. /*                                                                    */
  910. /*     Description:                                                   */
  911. /*        This routine is the executive routine for the rolodex       */
  912. /*     program.  It puts up the main menu, waits for a keypress, and  */
  913. /*     interpets the option chosen.                                   */
  914. /*                                                                    */
  915. /*     Parameters:  None                                              */
  916. /*                                                                    */
  917. /*     Results returned:  None                                        */
  918. /*                                                                    */
  919. /*     Calls:  show_node()                                            */
  920. /*             hide_cursor()                                          */
  921. /*             set1eptr()                                             */
  922. /*             abort()                                                */
  923. /*             insert_node()                                          */
  924. /*             edit_node()                                            */
  925. /*             delete_node()                                          */
  926. /*             save_list()                                            */
  927. /*                                                                    */
  928. /*     Called by:  main()                                             */
  929. /*                                                                    */
  930. /*     Globals referenced/modified:  current_view_node                */
  931. /*                                                                    */
  932. /**********************************************************************/
  933.  
  934. void main_menu (void)
  935.  
  936.    {
  937.    char         key;            /* Key pressed                  */
  938.    NODE far     *ptr;           /* Pointer to current view node */
  939.    unsigned int status;         /* Error tracking               */
  940.    unsigned int ext_scan_code;  /* TRUE/FALSE on keypress       */
  941.    unsigned int need_redraw;    /* Do we need to redraw node??  */
  942.    static char  *menu_line[] =  /* Bottom menu lines            */
  943.        {
  944.        "            I N T E L   R O L O D E X            ",
  945.        "     <--- backwards            ---> forwards     ",
  946.        "  I) Insert  D) Delete  E) Edit  S) Save  Q) Quit"
  947.        };
  948.  
  949.    /*******************************************************/
  950.    /* As long as the key pressed was not a 'Q' (for Quit) */
  951.    /* keep interpeting options.                           */
  952.    /*******************************************************/
  953.  
  954.    do
  955.        {
  956.  
  957.        /* Show the current view node */
  958.  
  959.        show_node (current_view_node);
  960.  
  961.        /* Put up bottom menu */
  962.  
  963.        _settextposition (MENU_ROW1, MENU_COL);
  964.        _outtext (menu_line[0]);
  965.        _settextposition (MENU_ROW2, MENU_COL);
  966.        _outtext (menu_line[1]);
  967.        _settextposition (MENU_ROW3, MENU_COL);
  968.        _outtext (menu_line[2]);
  969.  
  970.        /********************************************************/
  971.        /* We don't want to see the cursor while waiting for a  */
  972.        /* menu option.                                         */
  973.        /********************************************************/
  974.  
  975.        hide_cursor();
  976.  
  977.        /***********************************************************/
  978.        /* As long as we don't need to redraw, ask for another key */
  979.        /***********************************************************/
  980.  
  981.        do
  982.            {
  983.  
  984.            need_redraw = TRUE;
  985.  
  986.            /****************************************/
  987.            /* Get key, test for extended scan code */
  988.            /****************************************/
  989.  
  990.            key = getch();
  991.            if (key == 0)
  992.                {
  993.                ext_scan_code = TRUE;
  994.                key = getch();
  995.                }
  996.            else
  997.                ext_scan_code = FALSE;
  998.  
  999.            /*******************************/
  1000.            /* Based on key, decide option */
  1001.            /*******************************/
  1002.  
  1003.            switch (toupper (key))
  1004.                {
  1005.  
  1006.                /******************************************************/
  1007.                /* Left arrow: Set current view node to previous node */
  1008.                /******************************************************/
  1009.  
  1010.                case LEFT_ARROW:
  1011.                    if (ext_scan_code)
  1012.                        {
  1013.                        status = set1eptr (current_view_node, &ptr);
  1014.                        if (status == PASSED)
  1015.                            current_view_node = ptr->prev_node;
  1016.                        else
  1017.                            abort (status);
  1018.                        }
  1019.  
  1020.                    break;
  1021.  
  1022.                /**************************************************/
  1023.                /* Left arrow: Set current view node to next node */
  1024.                /**************************************************/
  1025.  
  1026.                case RIGHT_ARROW:
  1027.                    if (ext_scan_code)
  1028.                        {
  1029.                        status = set1eptr (current_view_node, &ptr);
  1030.                        if (status == PASSED)
  1031.                            current_view_node = ptr->next_node;
  1032.                        else
  1033.                            abort (status);
  1034.                        }
  1035.  
  1036.                    break;
  1037.  
  1038.                /******************/
  1039.                /* I: Insert node */
  1040.                /******************/
  1041.  
  1042.                case 'I':
  1043.                    status = insert_node();
  1044.                    if (status != PASSED)
  1045.                        abort (status);
  1046.                    break;
  1047.  
  1048.                /****************/
  1049.                /* E: Edit node */
  1050.                /****************/
  1051.  
  1052.                case 'E':
  1053.                    status = edit_node();
  1054.                    if (status != PASSED)
  1055.                        abort (status);
  1056.                    break;
  1057.  
  1058.                /******************/
  1059.                /* D: Delete node */
  1060.                /******************/
  1061.  
  1062.                case 'D':
  1063.                    status = delete_node();
  1064.                    if (status != PASSED)
  1065.                        abort (status);
  1066.                    break;
  1067.  
  1068.                /****************/
  1069.                /* S: Save list */
  1070.                /****************/
  1071.  
  1072.                case 'S':
  1073.                    status = save_list();
  1074.                    if (status != PASSED)
  1075.                        abort (status);
  1076.                    break;
  1077.  
  1078.                /***********************************/
  1079.                /* Q: Quit (don't set need_redraw) */
  1080.                /***********************************/
  1081.  
  1082.                case 'Q':
  1083.                    break;
  1084.  
  1085.                /************************************************/
  1086.                /* If it's some other key set need_redraw false */
  1087.                /* so that we won't redraw.                     */
  1088.                /************************************************/
  1089.  
  1090.                default:
  1091.                    need_redraw = FALSE;
  1092.                    break;
  1093.  
  1094.                } /** end switch **/
  1095.  
  1096.            } /** end do **/
  1097.        while (!need_redraw);
  1098.  
  1099.        } /** end do **/
  1100.    while (toupper (key) != 'Q');
  1101.  
  1102.    } /** end main_menu **/
  1103.  
  1104.